package acs.bridge.dao;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;

import java.io.InputStream;
import java.math.BigDecimal;
import java.sql.*;
import java.util.List;

/**
 * ACS
 * User: stas
 * Date: 13.04.13
 * Time: 14:11
 */
public class BridgeDAOImpl implements BridgeDAOInterface {

    private JdbcTemplate jdbcTemplate;

    private String db_url;
    private String db_name;
    private String db_username;
    private String db_password;


    @Override
    public void prc_start_meta_processing(String a_group_tag, String a_meta_tag) {

        this.jdbcTemplate.update("call BRIDGE.PCK_BRIDGE.PRC_START_META_PROCESSING(?,?)", new Object[]{a_group_tag, a_meta_tag});

    }

    @Override
    public void prc_finish_meta_processing() {
        this.jdbcTemplate.update("call BRIDGE.PCK_BRIDGE.PRC_FINISH_META_PROCESSING()");
    }

    @Override
    public BigDecimal fnc_start_transaction() {

        return (BigDecimal) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.PCK_BRIDGE.FNC_START_TRANSACTION()}");
                        callableStatement.registerOutParameter(1, Types.INTEGER);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getBigDecimal(1);
                    }


                }
        );
    }

    @Override
    public void prc_finish_transaction() {
        this.jdbcTemplate.update("call BRIDGE.PCK_BRIDGE.PRC_FINISH_TRANSACTION()");
    }

    @Override
    public BigDecimal fnc_start_raw_processing(final BigDecimal a_raw_id) {
        return (BigDecimal) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.PCK_BRIDGE.FNC_START_RAW_PROCESSING(?)}");
                        callableStatement.registerOutParameter(1, Types.INTEGER);
                        callableStatement.setBigDecimal(2, a_raw_id);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getBigDecimal(1);
                    }


                }
        );
    }

    @Override
    public void prc_finish_raw_processing(BigDecimal a_raw_id, BigDecimal a_index) {
        this.jdbcTemplate.update("{call BRIDGE.PCK_BRIDGE.PRC_FINISH_RAW_PROCESSING(?,?)}", new Object[]{a_raw_id, a_index});
    }

    @Override
    public BigDecimal fnc_check_disable() {
        return (BigDecimal) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.PCK_BRIDGE.FNC_CHECK_DISABLE()}");
                        callableStatement.registerOutParameter(1, Types.INTEGER);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getBigDecimal(1);
                    }


                }
        );
    }


    public List get_g_tt_bridge_raw() {
        return this.jdbcTemplate.queryForList("select * from TABLE(pck_bridge.get_g_tt_bridge_raw())");
    }


    @Override
    public void prc_msg(String a_text, String a_action, String a_param, Integer a_level, String a_error_tag) {
        this.jdbcTemplate.update("{call LOG_USER.PRC_MSG(?,?,?,?,?,?,?,?,?,?,?,?,?)}", new Object[]{a_text, a_action, a_param, null, 101, 0, null, a_error_tag, 0, null, null, 1, null});

    }

    @Override
    public void msg(String a_text, String a_action, String a_param, Integer a_level, String a_error_tag,Integer a_is_critical) {
        this.jdbcTemplate.update("{call BRIDGE.PCK_BRIDGE.MSG(?,?,?,?,?,?,?,?,?,?,?,?,?)}", new Object[]{a_text, a_action, a_param, null, a_level, 0, null, a_error_tag, a_is_critical, null, null, 1, null});

    }

    @Override
    public void set_cur_log_text(String a_log_text) {
        this.jdbcTemplate.update("{call BRIDGE.PCK_BRIDGE.SET_CUR_LOG_TEXT(?)}", new Object[]{a_log_text});

    }

    @Override
    public Integer fnc_is_error() {
        return ((BigDecimal) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.PCK_BRIDGE.FNC_IS_ERROR()}");
                        callableStatement.registerOutParameter(1, Types.INTEGER);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getBigDecimal(1);
                    }


                }
        )).intValue();
    }


    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;

    }

    @Override
    public JdbcTemplate getJdbcTemplate() {
        return this.jdbcTemplate;

    }

    /*  Получить конфигурацию модуля по тегу */
    public Clob get_module_config(final String a_module_tag) {

        return ((Clob) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.PCK_BRIDGE.GET_MODULE_CONFIG(?)}");
                        callableStatement.registerOutParameter(1, Types.CLOB); // or whatever type your function returns.
                        callableStatement.setString(2, a_module_tag);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getClob(1);
                    }


                }
        ));
    }

        /*  Получить текущее состоянии*/
    public Clob fnc_get_info() {

        return ((Clob) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.PCK_BRIDGE.FNC_GET_INFO()}");
                        callableStatement.registerOutParameter(1, Types.CLOB); // or whatever type your function returns.
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getClob(1);
                    }


                }
        ));
    }


    @Override
    public String get_string_field_by_id(final String a_group_tag, final String a_meta_tag, final BigDecimal a_id, final String a_filed_name, final String a_source) {
        return ((String) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.PCK_BRIDGE.GET_STRING_FIELD_BY_ID(?,?,?,?,?)}");
                        callableStatement.registerOutParameter(1, Types.VARCHAR);
                        callableStatement.setString(2, a_group_tag);
                        callableStatement.setString(3, a_meta_tag);
                        callableStatement.setBigDecimal(4, a_id);
                        callableStatement.setString(5, a_filed_name);
                        callableStatement.setString(6, a_source);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getString(1);
                    }


                }
        ));
    }


    @Override
    public Integer fnc_get_fr_id_exists(final String a_fr_id, final String a_group_tag, final String a_meta_tag) {

        return ((BigDecimal) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.FNC_GET_FR_ID_EXISTS(?,?,?)}");
                        callableStatement.registerOutParameter(1, Types.INTEGER);
                        callableStatement.setString(2, a_fr_id);
                        callableStatement.setString(3, a_group_tag);
                        callableStatement.setString(4, a_meta_tag);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getBigDecimal(1);
                    }


                }
        )).intValue();

    }


    @Override
    public BigDecimal get_object_exist(final String a_owner, final String a_table_name, final String a_object_name) {
        return (BigDecimal) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.PCK_BRIDGE.GET_OBJECT_EXIST(?,?,?)}");
                        callableStatement.registerOutParameter(1, Types.INTEGER);
                        callableStatement.setString(2, a_owner);
                        callableStatement.setString(3, a_table_name);
                        callableStatement.setString(4, a_object_name);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getBigDecimal(1);
                    }


                }
        );

    }


    @Override
    public BigDecimal get_log_sid() {

        return ((BigDecimal) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.PCK_BRIDGE.GET_LOG_SID()}");
                        callableStatement.registerOutParameter(1, Types.INTEGER);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getBigDecimal(1);
                    }


                }
        ));


    }

    @Override
    public BigDecimal get_task_id() {

        return ((BigDecimal) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.PCK_BRIDGE.GET_TASK_ID()}");
                        callableStatement.registerOutParameter(1, Types.INTEGER);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getBigDecimal(1);
                    }


                }
        ));


    }


    @Override
    public String fnc_schema_by_group(final String a_group_tag, final String a_meta_tag) {
        return (String) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection connection) throws SQLException {
                        CallableStatement callableStatement = connection.prepareCall("{? = call BRIDGE.FNC_GET_SCHEMA_BY_GROUP(?,?)}");
                        callableStatement.registerOutParameter(1, Types.VARCHAR);
                        callableStatement.setString(2, a_group_tag);
                        callableStatement.setString(3, a_meta_tag);
                        return callableStatement;
                    }
                },
                new CallableStatementCallback() {
                    public Object doInCallableStatement(CallableStatement callableStatement)
                            throws SQLException, DataAccessException {
                        callableStatement.execute();
                        return callableStatement.getString(1);
                    }


                }
        );
    }


    public void setDb_url(String db_url) {
        this.db_url = db_url;
    }

    public String getDb_username() {
        return db_username;
    }

    public void setDb_username(String db_username) {
        this.db_username = db_username;
    }

    public String getDb_password() {
        return db_password;
    }

    public void setDb_password(String db_password) {
        this.db_password = db_password;
    }

    public String getDb_url() {
        return db_url;
    }

    public String getDb_name() {
        return db_name;
    }

    public void setDb_name(String db_name) {
        this.db_name = db_name;
    }


    @Override
    public void prc_processing_error(String a_text) {
        this.jdbcTemplate.update("{call PCK_BRIDGE.PRC_PROCESSING_ERROR(?)}", new Object[]{a_text});

    }

    @Override
    public void final_processing(BigDecimal taskID, String a_proc_name) {
        this.jdbcTemplate.update("{call " + a_proc_name + "(?)}", new Object[]{taskID});
    }
}
